﻿using System;
using System.Threading;

namespace Microsoft.Practices.CompositeUI.Utility
{
    /// <summary>
    /// 	Base class for <see cref = "ReaderWriterLock" /> helper classes 
    /// 	<see cref = "ReaderLock" /> and <see cref = "WriterLock" />.
    /// </summary>
    /// <seealso cref = "ReaderLock" />
    /// <seealso cref = "WriterLock" />
    public abstract class LockBase : IDisposable
    {
        #region Fields & Properties

        private readonly Action _release;

        private readonly bool _timedOut;

        /// <summary>
        /// 	If a timeout was specified in the constructor, it returns whether the operation 
        /// 	succeeded or timed out.
        /// </summary>
        public bool TimedOut
        {
            get
            {
                return _timedOut;
            }
        }

        #endregion

        #region Constructors

        internal LockBase(Action<int> acquireIntTimeout, Action release, int timeout)
        {
            _release = release;
            try
            {
                acquireIntTimeout(timeout);
            }
            catch (ApplicationException)
            {
                _timedOut = true;
            }
        }

        internal LockBase(Action<TimeSpan> acquireTimeSpanTimeout, Action release, TimeSpan timeout)
        {
            _release = release;
            try
            {
                acquireTimeSpanTimeout(timeout);
            }
            catch (ApplicationException)
            {
                _timedOut = true;
            }
        }

        #endregion

        #region Implementation of IDisposable

        /// <summary>
        /// 	Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 	Called to free resources.
        /// </summary>
        /// <param name = "disposing">Should be true when calling from Dispose().</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing && !_timedOut)
            {
                _release();
            }
        }

        #endregion
    }
}